package com.kunyi.web.im.websocket;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.concurrent.ImmediateEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @ClassName WebSocketTransportServer
 * @Description WebSockert服务启动类
 * @Author zhenguo.zhuang
 * @Date 2024/03/29
 * @Version 1.0
 **/
@Component
@Slf4j
public class WebSocketTransportServer {

    @Value("${transport.websocket.bind_address}")
    private String host;
    @Value("${transport.websocket.bind_port}")
    private Integer port;
    @Value("${transport.websocket.netty.leak_detector_level}")
    private String leakDetectorLevel;
    @Value("${transport.websocket.netty.boss_group_thread_count}")
    private Integer bossGroupThreadCount;
    @Value("${transport.websocket.netty.worker_group_thread_count}")
    private Integer workerGroupThreadCount;
    @Value("${transport.websocket.netty.channel_idle_time}")
    private Integer channelIdleTime;
    /**
     * 负责接收客户端的连接请求
     */
    private EventLoopGroup bossGroup;
    /**
     * 负责处理已经建立连接的数据读写
     */
    private EventLoopGroup workerGroup;
    /**
     * nett服务端通道
     */
    private Channel serverChannel;
    /**
     * 保存所有的客户端channel
     */
    public final ChannelGroup channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
    /**
     * 管理通道，以及向客户端发送消息类
     */
    @Autowired
    TransportService service;



    /**
     * @author: zhenguo.zhuang
     * @Description 类被实例化时执行 执行初始化操作.
     * @Date 16:27 2024/3/29
     * @Param :
     * @return void
     **/
    @PostConstruct
    public void init() throws Exception{
        log.info("将资源泄漏探测器级别设置为极端{}",leakDetectorLevel);
        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.valueOf(leakDetectorLevel.toUpperCase()));
        //创建两个线程组
        bossGroup = new NioEventLoopGroup(bossGroupThreadCount);
        workerGroup = new NioEventLoopGroup(workerGroupThreadCount);
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new StompTransportServerInitializer( channelIdleTime));

        serverChannel = serverBootstrap.bind(host, port).sync().channel();
        log.info("webscoket服务启动,端口:{}",port);
    }

    /**
     * @author: zhenguo.zhuang
     * @Description 通道销毁时执行
     * @Date 16:26 2024/3/29
     * @Param :
     * @return void
     **/
    @PreDestroy
    public void shutdown() throws InterruptedException{
        try {
            serverChannel.close().sync();
        } finally {
            channelGroup.close();
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}
